﻿using System;

namespace Space2D_Utils
{
	[Serializable]
	public struct Vector2i128
	{
		public Vector2i128(Vector2i128 vec)
			: this()
		{
			Set(vec);
		}

		public Vector2i128(Vector2i128 dir, Int128 magnitude)
			: this()
		{
			Set(dir.Normalized() * magnitude);
		}

		public Vector2i128(Int128 x, Int128 y)
			: this()
		{
			Set(x, y);
		}

		public void Set(Vector2i128 vec)
		{
			Set(vec.X, vec.Y);
		}

		public void Set(Int128 x, Int128 y)
		{
			X = x;
			Y = y;

			SqrLength = X * X + Y * Y;
			SqrtLength = Int128.Sqrt(SqrLength);
		}

		public Vector2i128 Normalized()
		{
			return new Vector2i128(X / SqrtLength, Y / SqrtLength);
		}

		public static Int128 SqrDistance(Vector2i128 v1, Vector2i128 v2)
		{
			Int128 dx = v1.X - v2.X;
			Int128 dy = v1.Y - v2.Y;

			return dx * dx + dy * dy;
		}

		public static Vector2i128 Direction(Vector2i128 v1, Vector2i128 v2)
		{
			Vector2i128 dir = new Vector2i128(v1.X - v2.X, v1.Y - v2.Y);

			return dir.Normalized();
		}

		public static Int128 Distance(Vector2i128 v1, Vector2i128 v2)
		{
			return Int128.Sqrt(SqrDistance(v1, v2));
		}

		public static bool operator ==(Vector2i128 a, Vector2i128 b)
		{
			if (System.Object.ReferenceEquals(a, b))
			{
				return true;
			}

			return a.X == b.X && a.Y == b.Y;
		}

		public static bool operator !=(Vector2i128 a, Vector2i128 b)
		{
			if (System.Object.ReferenceEquals(a, b))
			{
				return true;
			}

			return a.X != b.X || a.Y != b.Y;
		}

		public override bool Equals(object obj)
		{
			return base.Equals(obj);
		}

		public override int GetHashCode()
		{
			return base.GetHashCode();
		}

		public override string ToString()
		{
			return "X " + X + ", Y " + Y;
		}

		public static Vector2i128 operator -(Vector2i128 a)
		{
			return new Vector2i128(-a.X, -a.Y);
		}

		public static Vector2i128 operator +(Vector2i128 a, Vector2i128 b)
		{
			return new Vector2i128(a.X + b.X, a.Y + b.Y);
		}

		public static Vector2i128 operator -(Vector2i128 a, Vector2i128 b)
		{
			return new Vector2i128(a.X - b.X, a.Y - b.Y);
		}

		public static Vector2i128 operator *(Vector2i128 a, Int128 b)
		{
			return new Vector2i128(a.X * b, a.Y * b);
		}

		public static Vector2i128 operator *(Int128 b, Vector2i128 a)
		{
			return new Vector2i128(a.X * b, a.Y * b);
		}

		public static Vector2i128 operator /(Vector2i128 a, Int128 b)
		{
			return new Vector2i128(a.X / b, a.Y / b);
		}

		public Int128 X { get; private set; }
		public Int128 Y { get; private set; }
		public Int128 SqrLength { get; private set; }
		public Int128 SqrtLength { get; private set; }
	}
}
